home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / TUGU10.ZIP / TUGU.DOC < prev    next >
Text File  |  1995-04-05  |  23KB  |  561 lines

  1.  
  2.           TTTTTT UU  UU  GGGG  UU  UU
  3.             TT   UU  UU GG     UU  UU
  4.             TT   UU  UU GG GGG UU  UU
  5.             TT   UU  UU GG  GG UU  UU
  6.             TT    UUUU   GGGG   UUUU
  7.  
  8.            The Ultimate Graphics Unit v1.0
  9.  
  10.            Released April 5, 1995
  11.  
  12.   Created by Jason Rennie   (quasi@locke.ccil.org)
  13.                  and
  14.            Elliot Waingold  (fortran.god@bitbytes.clark.net)
  15.  
  16.   SFVGA (the new standard) - SuperFast VGA
  17.  
  18.  WWW home page - http://www.ccil.org/~quasi/homepage.html
  19.  
  20.  * Code copyright 1995 by Elliot Waingold and Jason Rennie *
  21.  
  22.     Below is a quick listing of all the routines included in TUGU for your
  23.     reference.  Further in this document is a long listing of each
  24.     individual routine, including a detailed description of what it is
  25.     used for.
  26.  
  27. Procedure SetMode(mode : integer);         { video mode stuff }
  28. Procedure VGAMode;
  29.  
  30. Function  NewBuf : pointer;
  31. Procedure KillBuf(Buffer : pointer);    { buffer stuff }
  32. Procedure SetCurBuf(Buffer : pointer);
  33. Procedure BufToScreen(buffer : pointer);
  34. Procedure ScreenToBuf(buffer : pointer);
  35.  
  36. Procedure SetRGBPal(Var palette : palarray);
  37. Procedure GetRGBPal(Var palette : palarray);
  38. Procedure SetRGBPalette(r,g,b,color : byte);   { palette stuff }
  39. Procedure GetRGBPalette(Var r,g,b : byte; color : byte);
  40. Procedure ClrPal(Var palette : palarray);
  41. Procedure SmoothBlend(Var palette : palarray; Start, Finish : integer);
  42. Procedure RainbowPal(Var palette : palarray);
  43. Procedure RotateForward(Var palette : palarray);
  44. Procedure RotateBackward(Var palette : palarray);
  45. Procedure FadeIn(palette : palarray; speed : integer);
  46. Procedure FadeOut(palette : palarray; speed : integer);
  47. Procedure PaletteMerge(Pic1 : pointer; var Pal1 : PalArray;
  48.                        Pic2 : pointer; var Pal2, NewPal : PalArray);
  49.  
  50. Procedure WaitRetrace;
  51. Procedure WaitRefresh;
  52.  
  53. Procedure PutPix(x,y : integer);
  54. Function  GetPix(x,y : integer) : byte;
  55. Procedure ClrBuf(color : byte);                { plotting stuff }
  56. Procedure line(x1,y1,x2,y2 : integer);
  57. Procedure Rectangle(x1,y1,x2,y2 : integer);
  58. Procedure rectanglefill(x1,y1,x2,y2 : integer);
  59. Procedure Circle(Cx,Cy,y : integer);
  60.  
  61. Procedure PCXLoad(filename : string; Var palette : palarray; x,y : integer);
  62. Function  PCXLoadImage(filename : string; Var palette : palarray) : pointer;
  63. Procedure PCXSave(filename : string; palette : palarray; x1,y1,x2,y2 : integer);
  64. Procedure PCXSaveImage(filename : string; palette : palarray; ImagePtr : pointer); { image stuff }
  65. Procedure GetImage(x1, y1, x2, y2 : integer; imageptr : pointer);
  66. Procedure PutImage(x, y : integer; ImagePtr : pointer);
  67. Procedure PutTransparent(x, y : integer; tcolor : byte; ImagePtr : pointer);
  68. Procedure KillImage(ImagePtr : pointer);
  69.  
  70. Procedure InitSprite(var NewSprite : SpriteType; XSize, YSize : integer);
  71. Procedure InsertSpriteImage(var Sprite : SpriteType; ImagePtr : pointer;
  72.                             FrameNum : byte);
  73. Procedure DrawSprite(x, y : integer; var Sprite : SpriteType);
  74. Procedure UndrawSprite(x, y : integer; var Sprite : SpriteType);   { sprite }
  75. Procedure SetFrame(var Sprite : SpriteType; FrameNum : integer);   {  stuff }
  76. Procedure NextFrame(var Sprite : SpriteType);
  77. Procedure PrevFrame(var Sprite : SpriteType);
  78. Procedure KillSpriteFrame(var Sprite : SpriteType; FrameNum : integer);
  79. Procedure KillSprite(var Sprite : SpriteType);
  80.  
  81. Procedure LoadFont(Var font : pointer; fontname : string);
  82. Procedure Textxy(font : pointer; Var text2 : string; x,y : integer; size : byte);  { font stuff }
  83.  
  84.     There are also many constants and variable types which go along with
  85.     TUGU:
  86.  
  87. SW = 320;
  88. SH = 200;
  89. xmax = 319;
  90. ymax = 199;
  91.  
  92.     Anywhere you need the size of the screen or the maximum x or y values,
  93.     you may use the above constants.
  94.  
  95. NC = 256;
  96. ColorMax = NC-1;
  97.  
  98.     Anywhere you need the number of colors for the video mode or the maximum
  99.     color value, you may use the above constants.
  100.  
  101. MaxFrames = 16;
  102.  
  103.     The maxiumum number of frames that may be used in conjuction with the
  104.     sprite routines found in TUGU is 16.
  105.  
  106. VidPtr = ptr($A000, 0);
  107.  
  108.     Any time you need a pointer to the video memory, you may use VidPtr
  109.     instead of having to create a new pointer
  110.  
  111. palarray = array [0..ColorMax,1..3] of byte;
  112.  
  113.     If you would ever want to create your own palette or access palette
  114.     values individually, use the following format.  To set up your own,
  115.     put "mypal : palarray" in the "Var" section of your program.  A default
  116.     palette "pal" is provided for your convenience.
  117.  
  118. SpriteType = record
  119.   CurFrame, NumFrames : byte;
  120.   Width, Height : integer;
  121.   FramePtr : array[0..MaxFrames-1] of pointer;
  122.   BackGround : pointer;
  123. end;
  124.  
  125.     The above is the format used for the sprite.  Any time you want to set
  126.     up a new sprite, use "mysprite : SpriteType" in the "Var" section of your
  127.     program.
  128.  
  129. color : byte;    { Current drawing color }
  130.  
  131.     Instead of forcing you to include the desired drawing color with every
  132.     procedure you want to execute, we have set up a global variable called
  133.     "color" for you to use.  To change the current drawing color, simply
  134.     set "color" to the number you desire.
  135.  
  136. CurBuf : pointer;      { Pointer to current drawing buffer }
  137.  
  138.     This is another global variable meant to make things easier on you, the
  139.     programmer.  This variable controls where all data is sent to.  By
  140.     default, all data is sent to the video screen, but if you want to set
  141.     up your own video pages, you may use this in conjuction with the buffer
  142.     routines to do so.
  143.  
  144. time : longint absolute $0046:$c; { accesses internal timer }
  145.  
  146.     This is simply a nice useful variable which I stuck in to make it easy
  147.     to access the internal timer.  If you ever need to access it, you simply
  148.     need to set a variable equal to "time" and that variable will hold the
  149.     number of clock ticks that have elapsed since midnight.  One second is
  150.     equal to 18.2 clock ticks, so to convert from ticks to seconds, you should
  151.     divide by 18.2
  152.  
  153.  
  154. Procedure SetMode(mode : integer);
  155.  
  156.     This procedure will set the screen to any non-VESA mode.  All standard
  157.     modes up to VGA are included within this field.  SVGA can be set with
  158.     this procedure, but are limited to those specific to the graphics card.
  159.     Each card type has different numbers for the various SVGA modes.  This
  160.     is primarily used to move back into text mode from graphics.  The number
  161.     for the standard 80x25 color text mode is 3.
  162.  
  163.  
  164. Procedure VGAMode;
  165.  
  166.     This procedure automatically sets the video mode to 13h (320x200x256),
  167.     the mode that this graphics unit was built for.  This is essentially
  168.     the initialization line for this unit.
  169.  
  170.  
  171. Function NewBuf : pointer;
  172.  
  173.     Setting a pointer equal to NewBuf will allocate the necessary memory to
  174.     hold a page of video memory (64k).  Using a buffering system allows
  175.     the least amount of flicker and choppiness.
  176.  
  177.  
  178. Procedure KillBuf(buffer : pointer);
  179.  
  180.     This procedure will deallocate the memory for a buffer and allow the extra
  181.     memory to be used once again.
  182.  
  183.  
  184. Procedure SetCurBuf(buffer : pointer);
  185.  
  186.     This procedure tells TUGU on which buffer to perform graphics operations.
  187.     This allows the programmer to send information to a buffer and then when
  188.     all the necessary drawing is done, use BufToScreen to quickly present the
  189.     picture on the screen.  Redrawing the screen without using a buffering
  190.     system will often cause flickering when the animation becomes more
  191.     complex.
  192.  
  193.  
  194. Procedure BufToScreen(buffer : pointer);
  195.  
  196.     This will simply copy the virtual screen in the selected buffer to the
  197.     video screen with blazing speed.
  198.  
  199.  
  200. Procedure ScreenToBuf(buffer : pointer);
  201.  
  202.     This does the opposite of the above procedure, copying the information
  203.     in the video memory to a buffer.
  204.  
  205.  
  206. Procedure SetRGBPal(Var palette : palarray);
  207.  
  208.     This will set the entire VGA palette very quickly.  The palette is
  209.     composed of 256 colors each broken down into red, green and blue values,
  210.     hence the variable type palarray : array [0..255,1..3] of byte;
  211.     Each value can range from 0 to 63, 63 being full intensity.
  212.     If you intend to set only a portion of the palette, it is recommended
  213.     that you first get the standard palette using the below procedure.
  214.  
  215.  
  216. Procedure GetRGBPal(Var palette : palarray);
  217.  
  218.     The variable "pal" is NOT automatically set to the default palette.  This
  219.     procedure allows you to get the default palette and then deal with it
  220.     however you like.  As long as you use only SetRGBPal for setting the
  221.     palette, there are few other uses for this procedure.
  222.  
  223.  
  224. Procedure SetRGBPalette(r,g,b,color : byte);
  225.  
  226.     This procedure was included primarily to allow compatibility with the
  227.     BGI routines and also allow a simpler way to set the palette. 'r' is the
  228.     red value, 'g' is the green value, 'b' is the blue value and 'color' is
  229.     the color number.
  230.  
  231. Procedure GetRGBPalette(Var r,g,b : byte; color : byte);
  232.  
  233.     Gets the RGB values for a specified color value.
  234.  
  235.  
  236. Procedure ClrPal(Var palette : palarray);
  237.  
  238.     This will set all values of the "palette" variable to 0.  This procedure
  239.     will NOT set the actual video palette.  SetRGBPal must be used in
  240.     conjunction to set the palette.
  241.  
  242.  
  243. Procedure SmoothBlend(Var palette : palarray; start, finish : integer);
  244.  
  245.     This procedure takes the RGB values of the "start" and "finish" colors
  246.     and makes a smooth transition of colors between them and stores those
  247.     new colors in the "palette" array.  Once again, SetRGBPal must be used
  248.     to set the palette.
  249.  
  250.  
  251. Procedure RainbowPal(Var palette : palarray);
  252.  
  253.     This will create a palette which moves through all the colors in a
  254.     rainbow.  The following colors are set and then SmoothBlend is used to
  255.     make transition between them:
  256.  
  257.     0   black
  258.     1   red
  259.     43  yellow
  260.     86  green
  261.     128 cyan
  262.     171 blue
  263.     213 purple
  264.     255 red
  265.  
  266.     The palette is NOT set during the calling of the procedure.  To set the
  267.     palette, send the same variable to SetRGBPal.
  268.  
  269.  
  270. Procedure RotateForward(Var palette : palarray; start, finish : byte);
  271.  
  272.     This procedure will move each of the RGB values of palette ahead one color
  273.     value starting with "start" and ending with "finish".  The color in the
  274.     "finish" position is moved to the "start" position.  This does not set the
  275.     actual video palette.
  276.  
  277.  
  278. Procedure RotateBackward(Var palette : palarray; start, finish : byte);
  279.  
  280.     Same as above except backwards.
  281.  
  282.  
  283. Procedure FadeIn(palette : palarray; lag : integer);
  284.  
  285.     Given a palette and a lag, this procedure will turn the screen
  286.     completely black and then gradually increase the intensity until it
  287.     reaches the specifications dictated in the palette.  The smaller the
  288.     lag (to a minimum of 0), the quicker the fade will occur.  NOTE:
  289.     the global variable "pal" is used in changing the palette.  When the
  290.     fade is completed, "pal" will hold the current value of the palette.
  291.  
  292.  
  293. Procedure FadeOut(palette : palarray; lag : integer);
  294.  
  295.     See above.  Changes from full intensity palette to complete black.
  296.  
  297.  
  298. Procedure PaletteMerge(pic1 : pointer; var pal1 : palarray;
  299.                        pic2 : pointer; var pal2, newpal : palarray);
  300.  
  301.     Often when you load pictures or images, you are likely to find that you
  302.     will want to load two pictures at the same time and find that each of
  303.     the pictures has a completely different palette.  This procedure is the
  304.     solution to your troubles.  It will intelligently search through the
  305.     pictures finding which colors are most common in each of the pictures,
  306.     giving those colors priority in the new palette.  Each of the two
  307.     pictures must be images and must have their own separate palette.
  308.     Each image will be changed to accomodate for the new palette which will
  309.     be given in "newpal."  After a call to PaletteMerge, you can slap both
  310.     images on the screen and set the palette to newpal, and see that both
  311.     have proper coloring.
  312.     A quick note: color #0 is assumed to be black and will cause problems
  313.     if not.
  314.  
  315.  
  316. Procedure WaitRetrace;
  317.  
  318.     This waits until the current vertical retrace has been finished.
  319.     Using this procedure before updating the video screen will prevent snow
  320.     on older machines.  This would primarily be used in front of SetRGBPal
  321.     and BufToScreen statements.
  322.  
  323.  
  324. Procedure WaitRefresh;
  325.  
  326.     Similar to WaitRetrace, except that this pauses through an entire
  327.     vertical retrace, ensuring that whatever was last in the video memory
  328.     was completely seen on the video screen.
  329.  
  330.  
  331. Procedure PutPix(x,y : integer);
  332.  
  333.     Plots a pixel in the current drawing color.  This is one of the quickest
  334.     ways to plot a single pixel to the video screen, but should only be used
  335.     when a smaller number of pixels needs to be drawn.  As far as time per
  336.     pixel goes, routines such as PutImage or ClrBuf are MUCH faster.
  337.  
  338.  
  339. Function  GetPix(x,y : integer) : byte;
  340.  
  341.     Returns the color of the pixel at (x,y) in the current drawing buffer.
  342.  
  343.  
  344. Procedure ClrBuf(color : byte);
  345.  
  346.     A VERY quick way to turn the entire screen to a single color.  The
  347.     perfect way to clear the screen.
  348.  
  349.  
  350. Procedure Line(x1,y1,x2,y2 : integer);
  351.  
  352.     Your standard line procedure, drawing a line of width one between the
  353.     two points.  This is an EXTREMELY efficient procedure, rewritten entirely 
  354.     in assembler, using a separately developed algorithm which parallels
  355.     Bresenham for speed.  Clipping is implemented (if part of the line is not 
  356.     on the screen, it will not be drawn).
  357.  
  358.  
  359. Procedure Rectangle(x1,y1,x2,y2 : integer);
  360.  
  361.     Very quickly draws a rectangle in the current drawing color.  The upper
  362.     left corner of the rectangle is given by (x1,y1).  The lower right corner
  363.     of the rectangle is given by (x2,y2).  If one of the points is off the
  364.     screen, it will be moved as little as possible so that it is displayed
  365.     on the screen.  Example : point (-15,20) would be moved to (0,20).  If
  366.     both points are off the screen, the rectangle will not be displayed.
  367.  
  368.  
  369. Procedure RectangleFill(x1,y1,x2,y2 : integer);
  370.  
  371.     Draws a rectangle similar to above, except that it is filled.
  372.  
  373.  
  374. Procedure Circle(cx,cy,r : integer);
  375.  
  376.     Takes (cx,cy) as the center and draws a circle of radius "r" in the
  377.     current drawing color around the center.  This procedure again uses
  378.     Bresenham's circle algorithm and is very quick.
  379.  
  380.  
  381. Procedure PCXLoad(filename : string; Var palette : palarray; x,y : integer);
  382.  
  383.     The procedure loads the PCX file "filename" into the current drawing
  384.     buffer at location (x,y).  It does not set the palette, but rather
  385.     returns the palette of the image in the variable "palette."  This
  386.     procedure uses very quick file procedures and can load pcx images quite
  387.     speedily.
  388.     When loading PCX files it is suggested that you set the palette to black
  389.     before you load the file and then when it has been loaded, set the
  390.     palette with the appropriate variable.
  391.  
  392.  
  393. Function  PCXLoadImage(filename : string; Var palette : palarray) : pointer;
  394.  
  395.     PCXLoadImage is similar to PCXLoad in that it loads a PCX file, but
  396.     instead of loading directly into the current drawing buffer, it will
  397.     create an image out of the PCX file.  The function will return the
  398.     pointer of the image which holds the PCX image.  This image may then
  399.     be displayed using PutImage.
  400.  
  401.  
  402. Procedure PCXSave(filename : string; palette : palarray; x1,y1,x2,y2 : integer);
  403.  
  404.     This procedure will save the image which spans the current drawing buffer
  405.     from point (x1,y1) to (x2,y2) into the file "filename."  It will also
  406.     save the palette which is sent in "palette."
  407.  
  408.  
  409. Procedure PCXSaveImage(filename : string; palette : palarray; ImagePtr : pointer);
  410.  
  411.     Considering what you know of PCXLoadImage & PCXSave, you can probably
  412.     guess what this routine does.
  413.     It takes the image stored at the location in memory pointed to by
  414.     "ImagePtr" and saves that along with "palette" into the file indicated by
  415.     "filename."
  416.  
  417.  
  418. Procedure GetImage(x1,y1,x2,y2 : integer; ImagePtr : pointer);
  419.  
  420.     This procedure does pretty much what it says.  It takes the picture
  421.     enclosed by (x1,y1) and (x2,y2) and stores it in memory at the location
  422.     indicated by ImagePtr.
  423.     
  424.     (very important) NOTE : this procedure will NOT set up the memory space
  425.     for your image.  In other words, you will have to call a getmem procedure
  426.     to reserve space for your image.  The size reserved for the image must be
  427.     equal to (xsize * ysize + 4).
  428.  
  429.     Example:
  430.  
  431.         getmem(mypointer,(x2-x1)*(y2-y1)+4);
  432.         getimage(x1,y1,x2,y2,mypointer);
  433.  
  434.     The image format used by TUGU is a very simple one.  It is simply the
  435.     xsize and ysize followed by the information contained in the image (each 
  436.     color is equal to one byte).  The reason you must add four to the size of 
  437.     the image is that "xsize" and "ysize" are stored as word variables, which 
  438.     each take up two bytes of memory.
  439.  
  440.  
  441. Procedure PutImage(x,y : integer; ImagePtr : pointer);
  442.  
  443.     As it says, this procedure will take a image held in memory at location
  444.     "ImagePtr" and display it in the current drawing buffer at location (x,y).
  445.     It is done very quickly and efficiently, but has no special effects
  446.     included.
  447.  
  448.  
  449. Procedure PutTransparent(x,y : integer; tcolor : byte; ImagePtr : pointer);
  450.  
  451.     This procedure is similar to PutImage except that it will ignore and
  452.     therefore not plot all colors that are equal to "tcolor."  This can be
  453.     extremely useful for animation and images that do not conform to the
  454.     basic rectangular shape.  If you do any work with the mouse, you will
  455.     instantly see the benefits of this procedure.
  456.  
  457.  
  458. Procedure KillImage(Imageptr : pointer);
  459.  
  460.     If you ever want to free some memory that is being held by an image
  461.     that will no longer be used, this is the procedure for you.  Simply
  462.     send it the pointer for the image you want to trash and it shall be
  463.     destroyed.
  464.  
  465.  
  466. Procedure InitSprite(var NewSprite : spritetype; xsize,ysize : integer);
  467.  
  468.     This is the procedure for initialization of a SpriteType variable.  It
  469.     resets the current frame to zero and the number of frames to zero.  Also,
  470.     it sets the width and height of the sprite frames.
  471.  
  472.  
  473. Procedure InsertSpriteImage(Var sprite : spritetype; imageptr : pointer;
  474.                                 framenum : byte);
  475.  
  476.     This is the most important routine for building a sprite.  It inserts the
  477.     image pointed to by ImagePtr as frame number FrameNum in Sprite.  When
  478.     building an animated sprite, call this routine repeatedly until all
  479.     of the desired frames have been inserted.  The number of frames in the
  480.     sprite is updated if necessary.  NOTE: Make sure that image dimensions
  481.     match sprite dimensions set with InitSprite.  Also, Sprite must have been
  482.     previously initialized before passing it to this procedure.
  483.  
  484.  
  485. Procedure DrawSprite(x,y :integer; Var sprite : spritetype);
  486.  
  487.     This procedure draws the current frame of Sprite in the buffer/screen
  488.     (whichever is currently active) with upper left corner at (x,y).  Color
  489.     0 is treated as transparent.  This routine saves the background overwritten
  490.     by the sprite.
  491.  
  492.  
  493. Procedure UndrawSprite(x,y :integer; Var sprite : spritetype);
  494.  
  495.     This is where the background that was saved by DrawSprite is put to use.
  496.     This routine provides an easy way to restore what was behind a sprite before
  497.     is was drawn on the screen/buffer.  Use this after drawing one frame of the
  498.     sprite but before drawing the next.  The background is redrawn at (x,y).
  499.  
  500.  
  501. Procedure SetFrame(var sprite : spritetype; framenum : integer);
  502.  
  503.     Use this to set the frame that will be drawn next when DrawSprite is
  504.     called.
  505.  
  506.  
  507. Procedure NextFrame(var Sprite : SpriteType);
  508.  
  509.     Use this to set the current frame to be drawn by DrawSprite to the next
  510.     frame.  This effectively increments the current frame, going back to the
  511.     first if the current one is the last.  By loading up to sixteen different
  512.     sprite frames, one could use this procedure in conjunction with the other
  513.     sprite routines to "flip" through the animated sprite, perhaps moving it
  514.     around the screen at the same time.
  515.  
  516.  
  517. Procedure PrevFrame(var Sprite : SpriteType);
  518.  
  519.     This is similar to NextFrame, except it sets the current frame index to the
  520.     previous frame, going to the last one if current is the first.
  521.  
  522.  
  523. Procedure KillSpriteFrame(var Sprite : SpriteType; FrameNum : integer);
  524.  
  525.     Use this to remove a frame from Sprite and deallocate its memory.  I give
  526.     you the dire warning that if you kill a sprite frame, then you MUST
  527.     reinsert one at the same location before attempting to do ANYTHING else
  528.     with Sprite, including KillSprite.  This procedure should only be used
  529.     in conjunction with InsertSpriteImage to modify a frame.
  530.  
  531.  
  532. Procedure KillSprite(var Sprite : SpriteType);
  533.  
  534.     This is the antithesis of InitSprite.  It deallocates all memory used by
  535.     Sprite and leaves it unitialized.  Therefore, one cannot again use Sprite
  536.     until it is run through InitSprite again.
  537.  
  538.  
  539. Procedure LoadFont(Var font : pointer; fontname : string);
  540.  
  541.      This procedure is essentially the initialization for the TUGU font
  542.      engine.  It works similar to the way files do.  The pointer does NOT
  543.      need to be initialized, any old pointer will do.  Also needed is the
  544.      filename where the font is stored (usually ending in ".tf").
  545.      You may load numerous fonts for one program as long as there is enough
  546.      memory, but you need to used different pointers for the different fonts.
  547.      When you want to display any of the fonts, you will send the pointer
  548.      which was initialized for that font to "Textxy".
  549.  
  550.  
  551. Procedure Textxy(font : pointer; Var text2 : string; x,y : integer; size : byte);
  552.  
  553.      "Font" is the pointer which points to the location in memory where a
  554.      the information for a font is found.  "Text2" is the string that you want
  555.      to display.  "Textxy" will only display characters which are defined in
  556.      the font which is loaded.  If a character is not defined, a blank space
  557.      will be left in its place.  (x,y) is the location of the upper left
  558.      corner of where you want the font to appear on the screen.  Built in to
  559.      this procedure is a routine to enlarge the font if so desired.  The
  560.      procedure will multiply the font's size according to the number left
  561.      in "size."  If the normal size is desired, "size" should be set to 1.